#ifndef _DLM_MANAGER_
#define _DLM_MANAGER_

#include "dlm.h"
#include <iostream>
#include <vector>

using namespace std;
class DLM_Lock_Request;
class DLM_Resource;

/*============================================================================
  *** DLM_Manger ***
  =========================================================================== */

class DLM_Manager
{
public:
	DLM_Manager();
	
	/**
	* Returns true if immediate lock possible, false if lock queued
	*/
	bool lock(pid_t pid, int resource_id, int lock_type, bool non_block);

	/**
	* Returns pids which obtain the resource after it was unlocked
	*/
	vector<pid_t> unlock(pid_t pid, int resource_id);

	/**
	* Called by server on client timeout
	*/
	void timeout(pid_t pid, int resource_id);
	
	/**
	 * Returns true if pid holded resource lock
	 */
	bool try_lock(int resource_id, int lock_type);
private:
	int find_resource_position(int resource_id);

	//resources managed by DLM_Manager
	std::vector<DLM_Resource> resources;
};

/*============================================================================
  *** DLM_Lock_Request ***
  =========================================================================== */

class DLM_Lock_Request
{
public:
	DLM_Lock_Request();
	DLM_Lock_Request(pid_t pid, int lock_type);
	
	pid_t get_pid() const;
	int get_lock_type() const;
private:
	pid_t pid;
	int lock_type;
};

/*============================================================================
  *** DLM_Resource ***
  =========================================================================== */

class DLM_Resource
{
public:
	DLM_Resource();
	DLM_Resource(int resource_id);
	
	int get_id() const;
	
	/**
	 * Checkes whether lock is possible.
	 */
	bool is_lock_possible(int new_lock_type) const;
	
	/**
	 * Creates a new request and adds it to current locks.
	 */
	void add_lock(pid_t pid, int lock_type);
	
	/**
	 *  Creates a new request and adds it to waiting locks.
	 */
	void add_queue(pid_t pid, int lock_type);
	
	/**
	 * Removes from queue waiting request of specified process.
	 */
	void remove_waiting_pid(pid_t pid);
	
	/**
	 * Removes lock of specified process.
	 */
	void free_resource(pid_t pid);
	
	/**
	 *  Locks resource by first waiting process if it is possible.
	 */
	int lock_resource();
	
private:
	int resource_id;
	int current_lock_type;
	std::vector<DLM_Lock_Request> current_locks;
	std::vector<DLM_Lock_Request> waiting_locks;
};

#endif
